接續上一篇,
我們要先確認連過來的client是新的連線,
還是已經握手過的人要傳訊息然後判斷後續要做什麼,
如果是一個新的連線,我們必須先接受他,
所以要使用內建函數socket_accept(),
然後因為要做匿名聊天室,
我們給進來的連線一個不重複的id(使用uniqid函數),
//對創建的socket循環進行監聽,處理數據
function run(){
//循環,直到socket斷開
while(true){
socket_select($changes,$write,$except,NULL);
//循環取client傳過來的資料
foreach($changes as $sock){
//如果有新的client連接進來,則
if($sock==$this->master){
//接受一個socket連接
$client=socket_accept($this->master);
//给新連接進來的socket一個唯一的ID
$key=uniqid();
$this->sockets[]=$client; //將新連接進來的socket存進連接池
$this->users[$key]=array(
'socket'=>$client, //紀錄新連接進來client的socket訊息
'shou'=>false //標記該socket資源沒有完成握手
);
}else{
//do some
}
}
}
}
再來是要處理如果有人要傳訊息時的處理,
需要使用到socket_recv()內建函數接收資料,
還要根據socket在user池裡面查找相應的$k,ID
建立一個search()的自訂函數
//根據sock在users裡面查找相應的$k
function search($sock){
foreach ($this->users as $k=>$v){
if($sock==$v['socket'])
return $k;
}
return false;
}
然後組裝我們剛說的
//對創建的socket循環進行監聽,處理數據
function run(){
//循環,直到socket斷開
while(true){
socket_select($changes,$write,$except,NULL);
//循環取client傳過來的資料
foreach($changes as $sock){
//如果有新的client連接進來,則
if($sock==$this->master){
//接受一個socket連接
$client=socket_accept($this->master);
//给新連接進來的socket一個唯一的ID
$key=uniqid();
$this->sockets[]=$client; //將新連接進來的socket存進連接池
$this->users[$key]=array(
'socket'=>$client, //紀錄新連接進來client的socket訊息
'shou'=>false //標記該socket資源沒有完成握手
);
}else{
$len=0;
$buffer='';
//讀取該socket的訊息,注意:第二個參數是引用傳參即接收數據,第三個參數是接收數據的長度
do{
$l=socket_recv($sock,$buf,1000,0);
$len+=$l;
$buffer.=$buf;
}while($l==1000);
//根據socket在user池裡面查找相應的$k,即ID
$k=$this->search($sock);
}
}
}
}
下一篇繼續努力~~
謝謝您的文章
正好在學這部分
剛剛我在想能不能夠把 resource 作為陣列的 key
這樣在查詢時會方便很多
於是搜尋到這篇文章
裡面說到可以用 spl_object_hash 函數把 resource 轉為一個 unique id
這樣查詢的效能是 O(1)
如果這樣用沒什麼問題的話
我會偏好這種方法